package com.xfdmao.fcat.coin.base.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xfdmao.fcat.coin.base.constant.KLineConstant;
import com.xfdmao.fcat.coin.base.entity.KlineInfo;
import com.xfdmao.fcat.coin.base.entity.Matrix;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by cissa on 2019/7/28.
 */
public class  StrategyUtil {
    /**
     * 两条均线最佳做空的策略,找出长期均线和短期均线的值
     * @param klineInfos
     */
    public static List<Matrix> queryTwoMaStrategySellBest(List<KlineInfo> klineInfos,int maxMA,String symbol,double upperLeadFactor,
                                                      double gainFactor,String buyType,double protectionDownFactor) {
        System.out.println("找出最佳的两条做空均线值" );
        double [][] mns = new double[maxMA][maxMA];
        boolean [][] top20 = new boolean[maxMA][maxMA];
        String kineInfosJson = JSONArray.toJSONString(klineInfos); //由于在每次循环计算过程中，当发生
        for(int m=0;m<maxMA;m++) {
            for (int n = 0; n < maxMA; n++) {
                if(m>=n){
                    List<KlineInfo> klineInfoList = JSONArray.parseArray(kineInfosJson,KlineInfo.class);
                    List<KlineInfo> result = strategySellTwoAvg(klineInfoList, m+1, n+1,symbol,upperLeadFactor,gainFactor,protectionDownFactor);
                    double income = KlineInfoUtil.getSumIncomeRate(result,buyType);
                    if(income>0){
                        mns[m][n] = income;
                    }else{
                        mns[m][n] = 0.0;
                    }
                }else{
                    mns[m][n] = 0.0;
                }

            }
        }
        List<Matrix> matrixList = MatrixUtil.dealMatrix(mns);
        MatrixUtil.print(mns);


        Matrix matrix = MatrixUtil.queryMaxMatrix(mns);
        Integer maxM = matrix.getM();
        Integer maxN = matrix.getN();
        System.out.println("最佳的策略："+ JSONObject.toJSONString(matrix));
        return matrixList;
    }

    /**
     * 找出两条均线最佳的策略
     * @param klineInfos
     */
    public static List<Matrix> queryTwoMaStrategyBest(List<KlineInfo> klineInfos,int maxMA,String symbol,double upperLeadFactor,
                                                      double gainFactor,String buyType,double protectionDownFactor) {
        System.out.println("找出最佳的两条做多均线值" );
        double [][] mns = new double[maxMA][maxMA];
        boolean [][] top20 = new boolean[maxMA][maxMA];
        String kineInfosJson = JSONArray.toJSONString(klineInfos); //由于在每次循环计算过程中，当发生
        for(int m=0;m<maxMA;m++) {
            for (int n = 0; n < maxMA; n++) {
                if(m>=n){
                    List<KlineInfo> klineInfoList = JSONArray.parseArray(kineInfosJson,KlineInfo.class);
                    List<KlineInfo> result = strategyTwoAvg(klineInfoList, m+1, n+1,symbol,upperLeadFactor,gainFactor,protectionDownFactor);
                    double income = KlineInfoUtil.getSumIncomeRate(result,buyType);
                    if(income>0){
                        mns[m][n] = income;
                    }else{
                        mns[m][n] = 0.0;
                    }
                }else{
                    mns[m][n] = 0.0;
                }

            }
        }
        List<Matrix> matrixList = MatrixUtil.dealMatrix(mns);
        MatrixUtil.print(mns);


        Matrix matrix = MatrixUtil.queryMaxMatrix(mns);
        Integer maxM = matrix.getM();
        Integer maxN = matrix.getN();
        System.out.println("最佳的策略："+ JSONObject.toJSONString(matrix));
        return matrixList;
    }


    //找出涨幅大于5%，并且收盘价大于20MA，开盘价小于20MA
    public static void strategyUpDown(List<KlineInfo> klineInfos, Map<Date,Double> avgMap5, Map<Date,Double> avgMap10, Map<Date,Double> avgMap20) {
        System.out.println("左边是上涨百分点，上面是下跌的百分点\n" +
                "例如：[16][9],表示左边序列16（上涨16个点以上买入），右序列为9（下跌9个点以上卖出），总收益为179.11%");
        double p = 0.01;//初始值
        double q = 0.005;//每次递增的值
        double  paramM = p;

        double [][] mns = new double[30][30];
        boolean [][] top20 = new boolean[30][30];
        for(int m=0;m<30;m++) {
            double  paramN = p;
            for (int n = 0; n < 30; n++) {
                mns[m][n] = dealStrategyUpDown(klineInfos, paramM, paramN, avgMap5, avgMap10, avgMap20);
                paramN += q;
            }
            paramM +=q;
        }
        List<Matrix> matrixList = MatrixUtil.dealMatrix(mns);
        MatrixUtil.dealTop20(top20,matrixList);
        Matrix matrix = MatrixUtil.queryMaxMatrix(mns);
        Integer maxM = matrix.getM();
        Integer maxN = matrix.getN();
        MatrixUtil.print(mns);

        System.out.println(String.format("最大收益：%-8.4f\t买入上涨幅度：%-8.4f\t卖出下跌幅度：%-8.4f", dealStrategyUpDown(klineInfos,(maxM+1)*p,(maxN+1)*p, avgMap5, avgMap10, avgMap20),(maxM+1)*p,(maxN+1)*p));
        KlineInfoUtil.printBuySell(klineInfos);
    }



    public static double dealStrategyUpDown(List<KlineInfo> klineInfos, double paramM, double paramN, Map<Date,Double> avgMap5, Map<Date,Double> avgMap10, Map<Date,Double> avgMap20) {
        KlineInfoUtil.init(klineInfos);
        List<KlineInfo> result1 = new ArrayList<>();
        Map<Date, Double> incomeMap = new HashMap<>();
        boolean positionStatus = false;
        for (int i = 0; i < klineInfos.size(); i++) {
            KlineInfo klineInfo = klineInfos.get(i);
            //建仓
            //  if (klineInfo.dealGain() >= paramM && klineInfo.getClose() > avgMap5.get(klineInfo.getDate())) {
            if(!positionStatus){
                if (klineInfo.getGain() >= paramM ) {
                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }
            }

            //平仓
            if (klineInfo.getGain() <= -paramN) {
                if (positionStatus) {
                    klineInfo.setBuySellStatus(KLineConstant.BUYSELLSTATUS_SELL);
                    klineInfo.setIncomeRate(new BigDecimal(klineInfo.getClose()).subtract(new BigDecimal(result1.get(result1.size() - 1).getClose())).divide(new BigDecimal(klineInfo.getClose()), 6, BigDecimal.ROUND_DOWN).doubleValue());
                    result1.add(klineInfo);
                    positionStatus = !positionStatus;
                }
            }
        }
        double result = KlineInfoUtil.getSumIncomeRate(klineInfos);
        return result;
    }

    public static void strategyAvgAll(List<KlineInfo> klineInfos) {
        int ma = 1;
        int count = 120;
        List<Double> incomeList = new ArrayList<>();
        for(int i=1;i<=count;i++){
            Map<Date,Double> avgMap =  KlineInfoUtil.getAvg(klineInfos,i);
            List<KlineInfo> result = dealStrategyAvg(klineInfos,avgMap);
            double income = KlineInfoUtil.getSumIncomeRate(result);
            incomeList.add(income);
        }
        KlineInfoUtil.printIncomeList(incomeList);
    }
    public static double strategyAvg(List<KlineInfo> klineInfos, Integer upMaNum) {
        Map<Date,Double> upAvgMap =  KlineInfoUtil.getAvg(klineInfos,upMaNum);
        List<KlineInfo> result = dealStrategyAvg(klineInfos,upAvgMap);
        KlineInfoUtil.print(result,upAvgMap);
        double income = KlineInfoUtil.getSumIncomeRate(result);
        System.out.println("ma"+upMaNum+":"+income);
        return income;
    }

    public static List<KlineInfo> dealStrategyAvg(List<KlineInfo> klineInfos, Map<Date, Double> upAvgMap) {
        KlineInfoUtil.init(klineInfos);
        List<KlineInfo> result1 = new ArrayList<>();
        Map<Date, Double> incomeMap = new HashMap<>();
        boolean positionStatus = false;
        for (int i = 0; i < klineInfos.size(); i++) {
            KlineInfo klineInfo = klineInfos.get(i);
            if("0.0".equals(upAvgMap.get(klineInfo.getDate()).toString()))continue;
            //建仓
            if(!positionStatus){
                if (klineInfo.getClose() > upAvgMap.get(klineInfo.getDate()) ) {
                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }
            }else{
                //平仓
                if (klineInfo.getClose() < upAvgMap.get(klineInfo.getDate())) {
                    sellClose(result1, klineInfo);
                    positionStatus = !positionStatus;
                }
            }


        }
        return result1;
    }


    public static List<KlineInfo> strategyTwoAvg(List<KlineInfo> klineInfos, Integer upMaNum, Integer downMaNum,
                                                 String symbol,double upperLeadFactor,double gainFactor,
                                                 double protectionDownFactor) {
        Map<Date,Double> upAvgMap =  KlineInfoUtil.getAvg(klineInfos,upMaNum);
        Map<Date,Double> downAvgMap =  KlineInfoUtil.getAvg(klineInfos,downMaNum);
        List<KlineInfo> result = dealStrategyTwoAvg(klineInfos,upAvgMap,downAvgMap,symbol,upperLeadFactor,gainFactor,protectionDownFactor);
        return result;
    }

    private static List<KlineInfo> dealStrategyTwoAvg(List<KlineInfo> klineInfos, Map<Date, Double> upAvgMap, Map<Date, Double> downAvgMap,
                                                      String symbol,double upperLeadFactor,double gainFactor,double protectionDownFactor) {
        KlineInfoUtil.init(klineInfos);
        List<KlineInfo> result1 = new ArrayList<>();
        boolean positionStatus = false;
        for (int i = 0; i < klineInfos.size(); i++) {
            if(i<2)continue;
            KlineInfo klineInfo = klineInfos.get(i);
            if("0.0".equals(upAvgMap.get(klineInfo.getDate()).toString()))continue;
            if("EOS".equals(symbol)){
                if(!positionStatus) {  //如果空仓,则看是否需要建仓
                    //买入条件：
                    //1、当前收盘K线的长期均线值 小于 短期均线的值
                    if(upAvgMap.get(klineInfo.getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //2、当前收盘K线的长期均线的值  大于   上一根收盘K线的长期均线的值       即：长期均线往上走
                    if(upAvgMap.get(klineInfos.get(i-1).getDate()) > upAvgMap.get(klineInfo.getDate()))continue;

                    //3、当前收盘K线的收盘价高于短期均线的收盘价
                    if(klineInfo.getClose() < downAvgMap.get(klineInfo.getDate())) continue;

                    //4、当前收盘K线不能收长的上引线
                    if(KlineInfoUtil.isUpperLead(klineInfo,upperLeadFactor)) continue;

                    //5、当前收盘K线的上一个K线不能收上引线
                    if(KlineInfoUtil.isUpperLead(klineInfos.get(i-1),upperLeadFactor))continue;

                    //6、当前收盘K线涨幅大于-0.008
                    if(klineInfo.getGain()<gainFactor) continue;

                    //7、当前收盘K线的上一个K线涨幅大于-0.008
                    if(klineInfos.get(i-1).getGain()<gainFactor) continue;

                    //8、下跌那根K线的量不能是最近三根K线的最大量
                    if(KlineInfoUtil.bigVolDown(klineInfo,klineInfos.get(i-1),klineInfos.get(i-2)))continue;

                    //9、短期均线翻上
                    if(downAvgMap.get(klineInfos.get(i-1).getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //10、最近三根K线中不能有两根以上的K线下跌或小于均值
                    if(KlineInfoUtil.twoDown(klineInfo,klineInfos.get(i-1),klineInfos.get(i-2),downAvgMap))continue;
                    // klineInfo.getGain() + klineInfos.get(i-1).getGain() < 3 &&//11、当前收盘K线和上一根K线的涨幅不能超过3%
                    //(upAvgMap.get(klineInfo.getDate())- upAvgMap.get(klineInfos.get(i-1).getDate())) > 0.002d &&//12、当前收盘K线的长期均线的值-上一根K线  > 0.0045  (即走平不考虑)
                    //!(klineInfo.getGain()<0 && klineInfos.get(i-1).getGain()>0 && Math.abs(klineInfo.getGain()) >klineInfos.get(i-1).getGain()) &&//13、当前收盘K线的跌幅不能大于上一根K线的涨幅

                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }else {
                    //卖出条件：
                    //**保护价格，当价格跌破开仓多少止损**
                    double startPrice = result1.get(result1.size()-1).getClose();//建仓价格
                    double protectionPrice = new BigDecimal(startPrice).subtract(new BigDecimal(startPrice).multiply(new BigDecimal(protectionDownFactor))).doubleValue();
                    if(klineInfo.getLow() < protectionPrice){
                        klineInfo.setClose(protectionPrice);
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                        System.out.println("保护伞开启");
                    }else{
                        // 1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
                        if(klineInfo.getClose() > downAvgMap.get(klineInfo.getDate()) )continue;
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                    }
                }
            }else if("LTC".equals(symbol)){
                if(!positionStatus) {
                    //买入条件：
                    //1、当前收盘K线的长期均线值 小于 短期均线的值 (短期均线站上长期均线)
                    if(upAvgMap.get(klineInfo.getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //2、 上一根收盘K线的长期均线的值 大于 上一根收盘K线的短期均线的值（即： 1,2表示两条均线交叉）
                    //if(upAvgMap.get(klineInfos.get(i-1).getDate()) < downAvgMap.get(klineInfos.get(i-1).getDate()))continue;

                    //3、当前收盘K线的长期均线的值  大于  上一根收盘K线的长期均线的值（即：长期均线往上走）
                    if(upAvgMap.get(klineInfo.getDate())<upAvgMap.get(klineInfos.get(i-1).getDate()))continue;

                    //4、当前收盘K线的收盘价高于短期均线的收盘价 (收盘价站上短期均线)
                    if(klineInfo.getClose() < downAvgMap.get(klineInfo.getDate()))continue;

                    //5、当前收盘K线不能收长的上引线（上引线的定义：(最高价-收盘价)/(收盘价-最低价)>upperLeadFactor）
                    if(KlineInfoUtil.isUpperLead(klineInfo,upperLeadFactor))continue;

                    //6、当前收盘K线的上一个K线不能收上引线
                    if(KlineInfoUtil.isUpperLead(klineInfos.get(i-1),upperLeadFactor))continue;

                    //7、当前收盘K线涨幅大于gainFactor
                    if(klineInfo.getGain()<gainFactor)continue;

                    //8、当前收盘K线的上一个K线涨幅大于gainFactor
                    //if(klineInfos.get(i-1).getGain()<gainFactor)continue;

                    //9、最近三根收盘的K线不能都是下跌
                    if((klineInfos.get(i).getGain()<0 &&  klineInfos.get(i-1).getGain()<0 &&  klineInfos.get(i-2).getGain()<0))continue;

                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }else{
                    //卖出条件：
                    //**保护伞，当价格跌破开仓多少止损**
                    double startPrice = result1.get(result1.size()-1).getClose();//建仓价格
                    double protectionPrice = new BigDecimal(startPrice).subtract(new BigDecimal(startPrice).multiply(new BigDecimal(protectionDownFactor))).doubleValue();
                    if(klineInfo.getLow() < protectionPrice){
                        klineInfo.setClose(protectionPrice);
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                        System.out.println("保护伞开启");
                    }else{
                        //1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
                        if(klineInfo.getClose() > downAvgMap.get(klineInfo.getDate()))continue;
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                    }
                }
            }else if("BCH".equals(symbol)){
                if(!positionStatus) {  //如果空仓,则看是否需要建仓
                    //买入条件：
                    //1、当前收盘K线的长期均线值 小于 短期均线的值
                    if(upAvgMap.get(klineInfo.getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //2、当前收盘K线的长期均线的值  大于   上一根收盘K线的长期均线的值       即：长期均线往上走
                    if(upAvgMap.get(klineInfos.get(i-1).getDate()) > upAvgMap.get(klineInfo.getDate()))continue;

                    //3、当前收盘K线的收盘价高于短期均线的收盘价
                    if(klineInfo.getClose() < downAvgMap.get(klineInfo.getDate())) continue;

                    //4、当前收盘K线不能收长的上引线
                    if(KlineInfoUtil.isUpperLead(klineInfo,upperLeadFactor)) continue;

                    //5、当前收盘K线的上一个K线不能收上引线
                    if(KlineInfoUtil.isUpperLead(klineInfos.get(i-1),upperLeadFactor))continue;

                    //6、当前收盘K线涨幅大于-0.008
                    if(klineInfo.getGain()<gainFactor) continue;

                    //7、当前收盘K线的上一个K线涨幅大于-0.008
                  //  if(klineInfos.get(i-1).getGain()<gainFactor) continue;

                    //8、下跌那根K线的量不能是最近三根K线的最大量
                    if(KlineInfoUtil.bigVolDown(klineInfo,klineInfos.get(i-1),klineInfos.get(i-2)))continue;

                    //9、短期均线翻上
                    if(downAvgMap.get(klineInfos.get(i-1).getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //10、最近三根K线中不能有两根以上的K线下跌或小于均值
                    if(KlineInfoUtil.twoDown(klineInfo,klineInfos.get(i-1),klineInfos.get(i-2),downAvgMap))continue;
                    // klineInfo.getGain() + klineInfos.get(i-1).getGain() < 3 &&//11、当前收盘K线和上一根K线的涨幅不能超过3%
                    //(upAvgMap.get(klineInfo.getDate())- upAvgMap.get(klineInfos.get(i-1).getDate())) > 0.002d &&//12、当前收盘K线的长期均线的值-上一根K线  > 0.0045  (即走平不考虑)
                    //!(klineInfo.getGain()<0 && klineInfos.get(i-1).getGain()>0 && Math.abs(klineInfo.getGain()) >klineInfos.get(i-1).getGain()) &&//13、当前收盘K线的跌幅不能大于上一根K线的涨幅

                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }else {
                    //卖出条件：
                    //**保护价格，当价格跌破开仓多少止损**
                    double startPrice = result1.get(result1.size()-1).getClose();//建仓价格
                    double protectionPrice = new BigDecimal(startPrice).subtract(new BigDecimal(startPrice).multiply(new BigDecimal(protectionDownFactor))).doubleValue();
                    if(klineInfo.getLow() < protectionPrice){
                        klineInfo.setClose(protectionPrice);
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                        System.out.println("保护伞开启");
                    }else{
                        // 1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
                        if(klineInfo.getClose() > downAvgMap.get(klineInfo.getDate()) )continue;
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                    }
                }
            }else{//btc  获取其他测试
                if(!positionStatus) {
                    //买入条件：
                    //1、当前收盘K线的长期均线值 小于 短期均线的值 (短期均线站上长期均线)
                    if(upAvgMap.get(klineInfo.getDate()) > downAvgMap.get(klineInfo.getDate()))continue;

                    //2、 上一根收盘K线的长期均线的值 大于 上一根收盘K线的短期均线的值（即： 1,2表示两条均线交叉）
                    //if(upAvgMap.get(klineInfos.get(i-1).getDate()) < downAvgMap.get(klineInfos.get(i-1).getDate()))continue;

                    //3、当前收盘K线的长期均线的值  大于  上一根收盘K线的长期均线的值（即：长期均线往上走）
                    if(upAvgMap.get(klineInfo.getDate())<upAvgMap.get(klineInfos.get(i-1).getDate()))continue;

                    //4、当前收盘K线的收盘价高于短期均线的收盘价 (收盘价站上短期均线)
                    if(klineInfo.getClose() < downAvgMap.get(klineInfo.getDate()))continue;

                    //5、当前收盘K线不能收长的上引线（上引线的定义：(最高价-收盘价)/(收盘价-最低价)>upperLeadFactor）
                    if(KlineInfoUtil.isUpperLead(klineInfo,upperLeadFactor))continue;

                    //6、当前收盘K线的上一个K线不能收上引线
                    if(KlineInfoUtil.isUpperLead(klineInfos.get(i-1),upperLeadFactor))continue;

                    //7、当前收盘K线涨幅大于gainFactor
                    if(klineInfo.getGain()<gainFactor)continue;

                    //8、当前收盘K线的上一个K线涨幅大于gainFactor
                    //if(klineInfos.get(i-1).getGain()<gainFactor)continue;

                    //9、最近三根收盘的K线不能都是下跌
                    if((klineInfos.get(i).getGain()<0 &&  klineInfos.get(i-1).getGain()<0 &&  klineInfos.get(i-2).getGain()<0))continue;

                    buyOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }else{
                    //卖出条件：
                    //**保护伞，当价格跌破开仓多少止损**
                    double startPrice = result1.get(result1.size()-1).getClose();//建仓价格
                    double protectionPrice = new BigDecimal(startPrice).subtract(new BigDecimal(startPrice).multiply(new BigDecimal(protectionDownFactor))).doubleValue();
                    if(klineInfo.getLow() < protectionPrice){
                        klineInfo.setClose(protectionPrice);
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                        System.out.println("保护伞开启");
                    }else{
                        //1、当前收盘K线的收盘价 小于 当前收盘K线的短期均线的值
                        if(klineInfo.getClose() > downAvgMap.get(klineInfo.getDate()))continue;
                        sellClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                    }
                }
            }
        }
        return result1;
    }

    /**
     *
     * @param klineInfos
     * @param upMaNum
     * @param downMaNum
     * @param symbol
     * @param upperLeadFactor
     * @param gainFactor
     * @param protectionDownFactor
     * @return
     */
    public static List<KlineInfo> strategySellTwoAvg(List<KlineInfo> klineInfos, Integer upMaNum, Integer downMaNum,
                                                 String symbol,double upperLeadFactor,double gainFactor,
                                                 double protectionDownFactor) {
        Map<Date,Double> upAvgMap =  KlineInfoUtil.getAvg(klineInfos,upMaNum);
        Map<Date,Double> downAvgMap =  KlineInfoUtil.getAvg(klineInfos,downMaNum);
        List<KlineInfo> result = dealStrategySellTwoAvg(klineInfos,upAvgMap,downAvgMap,symbol,upperLeadFactor,gainFactor,protectionDownFactor);
        return result;
    }
    private static List<KlineInfo> dealStrategySellTwoAvg(List<KlineInfo> klineInfos, Map<Date, Double> upAvgMap, Map<Date, Double> downAvgMap,
                                                      String symbol,double upperLeadFactor,double gainFactor,double protectionDownFactor) {
        KlineInfoUtil.init(klineInfos);
        List<KlineInfo> result1 = new ArrayList<>();
        boolean positionStatus = false;
        for (int i = 0; i < klineInfos.size(); i++) {
            if(i<2)continue;
            KlineInfo klineInfo = klineInfos.get(i);
            if("0.0".equals(upAvgMap.get(klineInfo.getDate()).toString()))continue;
            {
                if(!positionStatus) {  //如果空仓,则看是否需要建仓
                    //买入条件：
                    //1、当前收盘K线的长期均线值 大于 短期均线的值      即：长期均线在短期均线的上面
                    if(upAvgMap.get(klineInfo.getDate()) < downAvgMap.get(klineInfo.getDate()))continue;

                    //2、当前收盘K线的长期均线的值  小于  上一根收盘K线的长期均线的值       即：长期均线往下走
                    if(upAvgMap.get(klineInfo.getDate())  > upAvgMap.get(klineInfos.get(i-1).getDate()) )continue;

                    //3、当前收盘K线的收盘价低于短期均线的收盘价     即价格跌破短期均线
                    if(klineInfo.getClose() > downAvgMap.get(klineInfo.getDate())) continue;

                    //4、当前收盘K线不能收长的下引线
                 //   if(KlineInfoUtil.isDownLead(klineInfo,upperLeadFactor)) continue;

                    //5、当前收盘K线的上一个K线不能收下引线
                //    if(KlineInfoUtil.isDownLead(klineInfos.get(i-1),upperLeadFactor))continue;

                    //6、当前收盘K线涨幅小于0.008
                //    if(klineInfo.getGain()>gainFactor) continue;

                    //7、当前收盘K线的上一个K线涨幅小于0.008
                 //   if(klineInfos.get(i-1).getGain()>gainFactor) continue;

                    //8、短期均线翻下
                    if(downAvgMap.get(klineInfo.getDate()) > downAvgMap.get(klineInfos.get(i-1).getDate()))continue;

                    //9、最近三根K线中不能有两根以上的K线上涨或大于均值
                //    if(KlineInfoUtil.twoUp(klineInfo,klineInfos.get(i-1),klineInfos.get(i-2),downAvgMap))continue;

                    sellOpen(result1, klineInfo);
                    positionStatus = !positionStatus;
                }else {
                    //卖出条件：
                    //**保护价格，当价格跌破开仓多少止损**
                    double startPrice = result1.get(result1.size()-1).getClose();//建仓价格
                    double protectionPrice = new BigDecimal(startPrice).add(new BigDecimal(startPrice).multiply(new BigDecimal(protectionDownFactor))).doubleValue();
                    if(klineInfo.getHigh() > protectionPrice){
                        klineInfo.setClose(protectionPrice);
                        buyClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                        System.out.println("保护伞开启");
                    }else{
                        // 1、当前收盘K线的收盘价 高于 当前收盘K线的短期均线的值
                        if(klineInfo.getClose() < downAvgMap.get(klineInfo.getDate()) )continue;
                        buyClose(result1, klineInfo);
                        positionStatus = !positionStatus;
                    }
                }
            }
        }
        return result1;
    }

    /**
     * 卖出平仓
     * @param result1
     * @param klineInfo
     * @return
     */
    private static void sellClose(List<KlineInfo> result1,  KlineInfo klineInfo) {
        klineInfo.setBuySellStatus(KLineConstant.BUYSELLSTATUS_SELL);
        klineInfo.setIncomeRate(new BigDecimal(klineInfo.getClose()).subtract(new BigDecimal(result1.get(result1.size() - 1).getClose())).divide(new BigDecimal(result1.get(result1.size() - 1).getClose()), 6, BigDecimal.ROUND_DOWN).doubleValue());
        result1.add(klineInfo);
    }

    /**
     * 买入开仓
     * @param result1
     * @param klineInfo
     * @return
     */
    private static void buyOpen(List<KlineInfo> result1,KlineInfo klineInfo) {
        klineInfo.setBuySellStatus(KLineConstant.BUYSELLSTATUS_BUY);
        result1.add(klineInfo);
    }

    /**
     * 卖出开仓
     * @param result1
     * @param klineInfo
     * @return
     */
    private static void sellOpen(List<KlineInfo> result1,KlineInfo klineInfo) {
        klineInfo.setBuySellStatus(KLineConstant.BUYSELLSTATUS_SELL_OPEN);
        result1.add(klineInfo);
    }

    /**
     * 买入平仓
     * @param result1
     * @param klineInfo
     * @return
     */
    private static void buyClose(List<KlineInfo> result1,  KlineInfo klineInfo) {
        klineInfo.setBuySellStatus(KLineConstant.BUYSELLSTATUS_BUY_CLOSE);
        KlineInfo klineInfoPrevious = result1.get(result1.size() - 1);
        klineInfo.setIncomeRate(new BigDecimal(klineInfoPrevious.getClose()).subtract(new BigDecimal(klineInfo.getClose())).divide(new BigDecimal(klineInfoPrevious.getClose()), 6, BigDecimal.ROUND_DOWN).doubleValue());
        result1.add(klineInfo);
    }
}
